/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.controller.admin;

import cn.easyplatform.lang.Strings;
import cn.easyplatform.messages.request.SimpleRequestMessage;
import cn.easyplatform.messages.vos.admin.CustomVo;
import cn.easyplatform.spi.service.AdminService;
import cn.easyplatform.type.IResponseMessage;
import cn.easyplatform.web.dialog.MessageBox;
import cn.easyplatform.web.service.ServiceLocator;
import org.zkoss.util.resource.Labels;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.select.SelectorComposer;
import org.zkoss.zk.ui.select.annotation.Listen;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zul.*;

import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class ConfigController extends SelectorComposer<Component> implements EventListener {

    @Wire("listbox#options")
    private Listbox options;

    private Map<String, Map<String, String>> model;

    @Override
    public void doAfterCompose(Component comp) throws Exception {
        super.doAfterCompose(comp);
        AdminService as = ServiceLocator.lookup(AdminService.class);
        IResponseMessage<?> resp = as.getConfig(new SimpleRequestMessage("config"));
        if (resp.isSuccess()) {
            model = (Map<String, Map<String, String>>) resp.getBody();
            redraw();
        } else {
            MessageBox.showMessage(resp);
            comp.detach();
        }
    }

    private void redraw() {
        options.getItems().clear();
        new TreeMap<>(model).forEach((name, entry) -> {
            Listgroup group = new Listgroup();
            Listcell span = new Listcell();
            span.setSpan(2);
            Label title = new Label(Strings.isBlank(name) ? Labels.getLabel("admin.config.default") : name);
            span.appendChild(title);
            Button add = new Button(Labels.getLabel("admin.config.add"));
            add.setIconSclass("z-icon-plus");
            add.setSclass("ml-2");
            add.setParent(span);
            add.addEventListener(Events.ON_CLICK, this);

            Button delete = new Button(Labels.getLabel("admin.config.delete"));
            delete.setIconSclass("z-icon-minus");
            delete.setSclass("ml-2");
            delete.setParent(span);
            delete.addEventListener(Events.ON_CLICK, this);
            span.setParent(group);
            group.setParent(options);
            group.setValue(name);
            entry.forEach((key, value) -> {
                Listitem row = new Listitem();
                row.appendChild(new Listcell(key));
                Listcell lc = new Listcell();
                Textbox textbox = new Textbox(value);
                textbox.setHflex("1");
                textbox.setInplace(true);
                lc.appendChild(textbox);
                row.appendChild(lc);
                options.appendChild(row);
            });
        });
    }

    @Override
    public void onEvent(Event event) throws Exception {
        if (event.getTarget().getNextSibling() == null) {//删除
            Listitem sel = options.getSelectedItem();
            if (sel == null)
                return;
            if (sel.getFirstChild().getFirstChild() == null)//现有的存在
                sel.setVisible(false);
            else//新增
                sel.detach();
        } else {//添加
            Listitem row = new Listitem();
            Listcell lc = new Listcell();
            Textbox key = new Textbox();
            key.setHflex("1");
            lc.appendChild(key);
            row.appendChild(lc);

            lc = new Listcell();
            Textbox value = new Textbox();
            value.setHflex("1");
            value.setInplace(true);
            lc.appendChild(value);
            row.appendChild(lc);

            Listgroup group = (Listgroup) event.getTarget().getParent().getParent();
            int idx = group.getIndex();
            if (group.getItemCount() > 0)
                idx = group.getItems().get(group.getItemCount() - 1).getIndex();
            options.getItems().add(idx + 1, row);
        }
    }

    @Listen("onClick=#load")
    public void onReload(Event event) {
        AdminService as = ServiceLocator.lookup(AdminService.class);
        IResponseMessage<?> resp = as.resetCache(new SimpleRequestMessage("System"));
        if (!resp.isSuccess())
            Clients.wrongValue(event.getTarget(), resp.getCode() + ":" + resp.getBody());
        else {
            model = (Map<String, Map<String, String>>) resp.getBody();
            redraw();
        }
    }

    @Listen("onClick=#save")
    public void onSave(Event event) {
        CustomVo entry = new CustomVo(0);
        options.getGroups().forEach(group -> {
            group.getItems().forEach(item -> {
                if (item.isVisible()) {
                    String key, value;
                    CustomVo.Entry e;
                    if (item.getFirstChild().getFirstChild() == null) {
                        key = ((Listcell) item.getFirstChild()).getLabel();
                        value = ((Textbox) item.getLastChild().getFirstChild()).getValue();
                        if (Strings.isBlank(value))
                            throw new WrongValueException(item.getLastChild().getFirstChild(), Labels.getLabel("common.input.not.empty", new Object[]{Labels.getLabel("debug.header.value")}));
                        if (value.equals(model.get(group.getValue()).get(key)))//没有修改
                            return;
                        e = new CustomVo.Entry(group.getValue(), key, value);
                        e.setFlag('U');
                    } else {//新增
                        Textbox txtKey = (Textbox) item.getFirstChild().getFirstChild();
                        Textbox txtValue = (Textbox) item.getLastChild().getFirstChild();
                        if (Strings.isBlank(txtKey.getValue()))
                            throw new WrongValueException(txtKey, Labels.getLabel("common.input.not.empty", new Object[]{Labels.getLabel("debug.header.name")}));
                        if (Strings.isBlank(txtValue.getValue()))
                            throw new WrongValueException(txtValue, Labels.getLabel("common.input.not.empty", new Object[]{Labels.getLabel("debug.header.value")}));
                        key = txtKey.getValue().trim();
                        value = txtValue.getValue().trim();
                        e = new CustomVo.Entry(group.getValue(), key, value);
                        e.setFlag('C');
                    }
                    entry.addEntry(e);
                } else {
                    String key = ((Listcell) item.getFirstChild()).getLabel();
                    String value = ((Textbox) item.getLastChild().getFirstChild()).getValue();
                    CustomVo.Entry e = new CustomVo.Entry(group.getValue(), key, value);
                    e.setFlag('D');
                    entry.addEntry(e);
                }
            });
        });
        if (entry.getEntries() == null)
            return;
        AdminService as = ServiceLocator.lookup(AdminService.class);
        IResponseMessage<?> resp = as
                .saveProject(new SimpleRequestMessage(entry));
        if (!resp.isSuccess())
            Clients.wrongValue(event.getTarget(), resp.getCode() + ":" + resp.getBody());
        else {
            model = (Map<String, Map<String, String>>) resp.getBody();
            redraw();
        }
    }

}
